<template>
  <el-card>
    <!-- 表单 -->
    <el-form style="width: 80%" label-width="100px" ref="ruleFormRef" :model="spuInfo" :rules="rules">
      <!-- 名称 -->
      <el-form-item prop="spuName" label="SPU名称">
        <el-input v-model="spuInfo.spuName" />
      </el-form-item>
      <!-- 品牌 -->
      <el-form-item prop="tmId" label="SPU品牌">
        <el-select v-model="spuInfo.tmId" placeholder="请选择">
          <el-option v-for="tm in trademarkList" :key="tm.id" :label="tm.tmName" :value="tm.id" />
        </el-select>
      </el-form-item>
      <!-- 描述 -->
      <el-form-item prop="description" label="SPU描述">
        <el-input v-model="spuInfo.description" type="textarea" rows="4" />
      </el-form-item>
      <!-- 图片 -->
      <el-form-item prop="spuImageList" label="SPU图片">
        <!-- 图片上传 -->
        <el-upload
          v-model:file-list="imgInfoList"
          multiple
          :action="BASE_URL + '/admin/product/fileUpload'"
          list-type="picture-card"
          :on-success="handleUpload"
          :on-preview="handlePictureCardPreview"
          :on-remove="handleRemove"
        >
          <el-icon><Plus /></el-icon>
        </el-upload>
      </el-form-item>
      <!-- 销售属性 -->
      <el-form-item prop="spuSaleAttrList" label="销售属性">
        <el-select v-model="selectedSaleAttrId" style="margin-right: 10px" :placeholder="placeholderText">
          <el-option v-for="bsa in enabledSaleAttrList" :key="bsa.id" :label="bsa.name" :value="bsa.id + '-' + bsa.name" />
        </el-select>
        <el-button type="primary" :icon="Plus" :disabled="!selectedSaleAttrId || enabledSaleAttrList.length === 0" @click="addSaleAttr()">添加销售属性</el-button>
        <!-- 表格 -->
        <el-table :data="saleAttrList" stripe border style="width: 100%; margin-top: 10px">
          <el-table-column label="序号" align="center" type="index" width="60" />
          <el-table-column prop="saleAttrName" label="属性名" width="200" />
          <el-table-column label="属性值名称列表">
            <template v-slot="{row}">
              <!-- 动态标签 -->
              <el-tag
                v-for="item in row.spuSaleAttrValueList"
                :key="item.is"
                closable
                @close="handleClose(row, item.saleAttrValueName)"
                style="margin-right: 5px"
              >
                {{ item.saleAttrValueName }}
              </el-tag>
              <el-input
                v-if="row.isShowEdit"
                ref="InputRef"
                v-model="inputValue"
                size="small"
                @keyup.enter="$event => $event.target.blur()"
                @blur="handleInputConfirm(row)"
                style="width: 100px"
              />
              <el-button v-else size="small" @click="showInput(row)">+</el-button>
            </template>
          </el-table-column>
          <el-table-column label="操作" align="center" width="200">
            <template v-slot="{row}">
              <el-popconfirm title="确定要删除该属性吗？" @confirm="deleteSaleAttr(row)" width="220">
                <template #reference>
                  <el-button type="danger" :icon="Delete" size="small"></el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
      </el-form-item>
      <!-- 按钮 -->
      <el-form-item label="">
        <el-button type="primary" @click="saveOrUpdate()">保存</el-button>
        <el-button @click="cancel()">取消</el-button>
      </el-form-item>
    </el-form>
  </el-card>
</template>
<script lang="ts">
export default {
  name: 'SpuForm'
}
</script>
<script lang="ts" setup>
import {computed, nextTick, onBeforeUnmount, onMounted, reactive, ref, watch} from 'vue'

// 引入图标组件
import { Delete, Edit, InfoFilled, Plus } from '@element-plus/icons-vue'
// 引入消息提示组件
import {ElMessage, ElMessageBox} from 'element-plus'
import type { UploadFile, UploadFiles, UploadProps, ElInput, FormInstance, FormRules } from 'element-plus'

// 引入Spu组件显示状态标识
import {SpuStatus} from '../SpuStatus'

// 引入分类仓库
import {useCategoryStore} from '@/stores/category'
const categoryStore = useCategoryStore()

// 引入品牌相关的接口函数及接口类型
import {getTrademarkListApi} from '@/api/product/trademark'
import type {TrademarkListModel} from '@/api/product/model/trademark'
// 引入SPU相关的接口函数及接口类型
import {getBaseSaleAttrListApi, getSpuImageListByIdApi, getSpuSaleAttrListByIdApi, addOrUpdataSpuInfoApi} from '@/api/product/spu'
import type {SpuModel, SpuSaleAttrListModel, SpuImageListModel, BaseSaleAttrListModel, SpuImageModel, SpuSaleAttrModel} from '@/api/product/model/spuModel'

// 引入PubSub
import PubSub from 'pubsub-js'
// 接收父组件传递的方法
const emits = defineEmits(['changeIsShow'])
// 定义spu对象
const spuInfo = reactive<SpuModel>({
  id: undefined,
  spuName: '',
  description: '',
  spuSaleAttrList: [], // 销售属性对象数组
  spuImageList: [] // spu图片对象的数组
})
const trademarkList = ref<TrademarkListModel>([]) // 定义品牌对象数组
const baseSaleAttrList = ref<BaseSaleAttrListModel>([]) // 定义基础销售属性对象数组
const saleAttrList = ref<SpuSaleAttrListModel>([]) // 定义销售属性对象数组 
const imgInfoList = ref<SpuImageListModel>([]) // 定义图片列表数组
const BASE_URL = import.meta.env.VITE_API_URL // 图片上传的基础路径
const dialogImageUrl = ref('') // 预览图片的地址
const dialogVisible = ref(false) // 图片预览对话框是否显示的标识
const selectedSaleAttrId = ref<string>('') // 选择的销售属性组合

const InputRef = ref<InstanceType<typeof ElInput>>() // 属性值名称输入框实例
const inputValue = ref<string>() // 属性值名称文本框输入值
// 存储输入值
const handleInputConfirm = (row: SpuSaleAttrModel) => {
  // 去除两端空字符
  const val = inputValue.value?.trim()
  if (!val) {
    ElMessage.warning('属性值名称不能为空')
    row.isShowEdit = false
    inputValue.value = ''
    return
  }
  // 判断属性值名称是否存在
  const index = row.spuSaleAttrValueList.findIndex(item => item.saleAttrValueName === val)
  if (index !== -1) {
    ElMessage.warning('属性值名称不能重复')
    row.isShowEdit = false
    inputValue.value = ''
    return 
  }
  // 更新属性值对象数组
  row.spuSaleAttrValueList.push({
    baseSaleAttrId: row.baseSaleAttrId as number,
    saleAttrName: row.saleAttrName,
    saleAttrValueName: val,
    spuId: spuInfo.id
  })
  row.isShowEdit = false
  inputValue.value = ''
}
// 显示输入框
const showInput = (row: SpuSaleAttrModel) => {
  row.isShowEdit = true
  nextTick(() => {
    // 获取焦点
    InputRef.value?.focus()
  })
}
// 移除当前属性值
const handleClose = (row: SpuSaleAttrModel, name: string) => {
  const index = row.spuSaleAttrValueList.findIndex((item) => item.saleAttrValueName === name)
  row.spuSaleAttrValueList.splice(index, 1)
}
// 移除当前行 属性名
const deleteSaleAttr = (row: SpuSaleAttrModel) => {
  const index = saleAttrList.value.findIndex(item => item.saleAttrName === row.saleAttrName)
  saleAttrList.value.splice(index, 1)
}

// 计算属性 有效的销售属性对象列表数据
const enabledSaleAttrList = computed(() => {
  return baseSaleAttrList.value.filter(item => {
    return saleAttrList.value.findIndex(sa => sa.saleAttrName === item.name) === -1
  })
})
// 计算属性 默认显示文本
const placeholderText = computed(() => {
  const {length} = enabledSaleAttrList.value
  return length > 0 ? `还有${length}个未选择`: '没有了'
})

// 获取品牌
const getTrademarkList = async () => {
  trademarkList.value = await getTrademarkListApi(categoryStore.category3Id as number)  
}
// 获取基础销售属性
const getBaseSaleAttrList =async () => {
  baseSaleAttrList.value = await getBaseSaleAttrListApi()
}
// 获取销售属性
const getSaleAttrList =async () => {
  saleAttrList.value = await getSpuSaleAttrListByIdApi(spuInfo.id as number)
}
// 获取图片列表
const getImgInfoList =async () => {
  imgInfoList.value = await getSpuImageListByIdApi(spuInfo.id as number)
  // 上传图片列表展示 图片路径属性应为url
  imgInfoList.value.forEach(item => {
    item.url = item.imgUrl
  })
}
// 取消
const cancel = () => {
  emits('changeIsShow', SpuStatus.Spu_List)
}

// 文件成功上传的回调
const handleUpload = (response: any, uploadFile: UploadFile, uploadFiles: UploadFiles) => {
  // 更新数据
  imgInfoList.value = uploadFiles as any
  imgInfoList.value.length === 1 && ruleFormRef.value?.clearValidate('spuImageList')
}
// 列表中移除图片
const handleRemove: UploadProps['onRemove'] = (uploadFile, uploadFiles) => {
  console.log(uploadFile, uploadFiles)
}
// 预览图片
const handlePictureCardPreview: UploadProps['onPreview'] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url!
  dialogVisible.value = true
}

// 添加销售属性
const addSaleAttr = () => {
  const [id, name] = selectedSaleAttrId.value?.split('-') as string[]
  saleAttrList.value.push({
    spuId: spuInfo.id,
    saleAttrName: name,
    baseSaleAttrId: +id,
    spuSaleAttrValueList: [],
  })
  // 清空输入框
  selectedSaleAttrId.value = ''
}

// 表单校验规则
const rules = reactive<FormRules>({
  spuName: [{ required: true, message: 'SPU名称不能为空', trigger: 'blur' }],
  tmId: [{ required: true, message: 'SPU品牌必须选择', trigger: 'change' }],
  description: [{ required: true, message: 'SPU描述不能为空', trigger: 'blur' }],
  spuImageList: [{ required: true, message: 'SPU图片至少需要上传一张', trigger: 'change' }],
  spuSaleAttrList: [{ required: true, message: 'SPU销售属性至少要有一个', trigger: 'change' }]
})
// 获取表单实例
const ruleFormRef = ref<FormInstance>()
// 侦听
watch(imgInfoList, (val) => {
  spuInfo.spuImageList = val
}, {immediate: true})
watch(saleAttrList, (val) => {
  spuInfo.spuSaleAttrList = val
}, {immediate: true})

// 保存
const saveOrUpdate = () => {  
  ruleFormRef.value?.validate(async (valid) => {
    // 规则校验未通过
    if (!valid) return
    // 整合请求参数
    imgInfoList.value = imgInfoList.value.map(item => ({
      spuId: spuInfo.id,
      imgName: item.name as string,
      imgUrl: item.response?.data || item.imgUrl
    }))
    saleAttrList.value = saleAttrList.value.filter(item => item.spuSaleAttrValueList.length)
    try {
      await addOrUpdataSpuInfoApi({
        ...spuInfo,
        category3Id: categoryStore._category3Id,
        spuImageList: imgInfoList.value,
      }) 
      ElMessage.success('操作成功')
      emits('changeIsShow', SpuStatus.Spu_List)
    } catch (error: any) {
      ElMessage.warning(error.message)
    }
  })
}


// 组件挂载完毕
onMounted(() => {
  getTrademarkList()
  getBaseSaleAttrList()
  // 订阅
  PubSub.subscribe('getSpuInfo', (name, val) => {
    Object.assign(spuInfo, val)   
    getSaleAttrList()
    getImgInfoList()
  })
})
// 组件销毁前
onBeforeUnmount(() => {
  // 取消订阅
  PubSub.unsubscribe('getSpuInfo')
})

</script>
<style scoped>
</style>